const db = uniCloud.database()
const dbCmd = db.command
const dbHelper = require("db-helper")
const moment = require('moment-timezone');
const {
	wxPubConfig
} = require("config")
const WxPubApi = require("wx-public-api");
const wxPubApi = new WxPubApi();
const payUtil = require("pay-util")
const oneHourInMills = 60 * 60 * 1000

const createNewOrderMsg = (openId, order, buyMan, templateID) => {
	let phone = order.user_phone.substring(0, 3) + '****' + order.user_phone.substring(7, 11);
	// let goods_name = order.goods_name.slice(0, 30)
	let goods_name = ''
	if (order.type == 'goods') {
		if (order.items[0].goods_name.length > 30) {
			goods_name = order.items[0].goods_name.slice(0, 30) + '...'
		} else {
			goods_name = order.items[0].goods_name
		}
	} else if (order.type == 'subscribe') {
		goods_name = order.items[0].script_name
	}

	let orderType = '自有'
	switch (order.channel) {
		case 'self':
			orderType = '自有'
			break;
		case 'lianlian':
			orderType = '联联周边游'
			break;
		case 'lvhuasuan':
			orderType = '旅划算'
			break;
		case 'xialvqingziyou':
			orderType = '侠侣亲子游'
			break;
		default:
			break;
	}
	return {
		touser: openId,
		// template_id: "5MRNZMy2-lLaGHascndunMi5tVrGvedK01TH89Rx6dM",
		template_id: templateID,
		miniprogram: {
			appid: "wxa7e5444036dea6af",
			pagepath: `pagesAdmin/platform/order/order-detail?id=${order._id}`
		},
		data: {
			first: {
				value: "收到一条新的订单"
			},
			orderItemName: {
				value: '商品名'
			},
			orderItemData: {
				value: goods_name
			},
			tradeDateTime: {
				value: moment().tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")
			},
			orderType: {
				value: orderType
			},
			customerInfo: {
				value: `${buyMan.nickname || '微信用户'} ID: ${buyMan.id} ${phone}`
			},
			remark: {
				value: `请尽快处理`
			}
		}
	}
}

const createMsg = (openId, order, incomes, templateID) => {
	console.log("incomesItem: ", incomes);
	var goodsName = order.items[0].goods_name;
	if (goodsName.length > 30) {
		goodsName = goodsName.substring(0, 30) + '...'
	}
	let phone = order.user_phone.substring(0, 3) + '****' + order.user_phone.substring(7, 11);
	let t = [];
	incomes.forEach(item => {
		t.push(`${item.type}：${(item.value / 100).toFixed(2)}元`);
	})
	let remark = ''
	if (!incomes[0].shareMan) {
		remark = `${goodsName}\n购买人：${order.user_nickname || '微信用户'}\n购买人手机：${phone}`
	} else {
		remark = `${goodsName}\n购买人：${order.user_nickname || '微信用户'}\n购买人手机：${phone}\n分享人：${incomes[0].shareMan}`
	}
	return {
		touser: openId,
		template_id: templateID,
		miniprogram: {
			appid: "wx609a0a547e98415d",
			pagepath: "pagesUser/platform/orders"
		},
		data: {
			first: {
				value: "恭喜您获得收益！"
			},
			keyword1: {
				value: `${t.join("\n")}`
			},
			keyword2: {
				value: `${(order.total_fee / 100).toFixed(2)}元`
			},
			keyword3: {
				value: moment().tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss")
			},
			remark: {
				value: remark
			}
		}
	}
}

const createSubscribeMsg = (openId, order, motorcade, templateID, templateName, remark) => {
	let status = ''
	switch (motorcade.status) {
		case 0:
			status = '拼车中'
			break;
		case 1:
			status = '待分配主持人'
			break;
		case 2:
			status = '待接单'
			break;
		case 3:
			status = '主持人已接单'
			break;
		case 4:
			status = '进行中'
			break;
		case 5:
			status = '已结束'
			break;
		case -1:
			status = '已取消'
			break;
		default:
			break;
	}
	let msg = null
	switch (templateName) {
		case '预约状态更新通知':
			msg = {
				touser: openId,
				template_id: templateID,
				miniprogram: {
					appid: "wx609a0a547e98415d",
					pagepath: "pagesFoo/order/order"
				},
				data: {
					first: {
						value: "预约成功！"
					},
					keyword1: {
						value: `${ motorcade.name }`
					},
					keyword2: {
						value: order._id
					},
					keyword3: {
						value: status
					},
					remark: {
						value: remark
					}
				}
			}
			break;
		case '预约成功通知':
			msg = {
				touser: openId,
				template_id: templateID,
				miniprogram: {
					appid: "wx609a0a547e98415d",
					pagepath: "pagesFoo/order/order"
				},
				data: {
					first: {
						value: "您预约的剧本已成功"
					},
					keyword1: {
						value: '剧本杀'
					},
					keyword2: {
						value: order.items[0].room_name
					},
					keyword3: {
						value: order.items[0].store_name
					},
					keyword4: {
						value: moment(order.items[0].start_time).tz("Asia/Shanghai").format(
							"YYYY-MM-DD HH:mm:ss") + ' ~ ' + moment(order.items[0].end_time).tz(
							"Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss"),
					},
					remark: {
						value: remark
					}
				}
			}
			break;
		case '预约失败通知':
			msg = {
				touser: openId,
				template_id: templateID,
				miniprogram: {
					appid: "wx609a0a547e98415d",
					pagepath: "pagesFoo/order/order"
				},
				data: {
					first: {
						value: "预约失败"
					},
					keyword1: {
						value: '剧本杀'
					},
					keyword2: {
						value: '包间已被其他人预定'
					},
					keyword3: {
						value: order.items[0].store_name
					},
					keyword4: {
						value: moment(order.items[0].start_time).tz("Asia/Shanghai").format(
							"YYYY-MM-DD HH:mm:ss") + ' ~ ' + moment(order.items[0].end_time).tz(
							"Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss"),
					},
					remark: {
						value: remark
					}
				}
			}
			break;
		default:
			break;
	}
	return msg
}

// 发送预约通知
const sendSubscribeNotice = async (user, order, motorcade, remark, templateName) => {
	try {
		if (user.wx_unionid) {
			let openId = await getOpenId(user.wx_unionid, user.city)
			if (openId) {
				let temp = await dbHelper.getOne('t3ds-region', {
					'city.value': user.city
				})
				let tempId = temp.templateMsgs.find(item => {
					return item.templateName == templateName
				}).templateID
				let msg = createSubscribeMsg(openId, order, motorcade, tempId, templateName, remark);
				await wxPubApi.sendTemplateMsg(user.city, msg);
			} else {
				console.warn('用户未关注公众号，无法发送通知，用户id: ', user.id)
			}
		} else {
			console.warn('用户未关注公众号，无法发送通知，用户id', user.id)
		}
	} catch (e) {
		console.error(e)
	}
}

const getOpenId = async (unionId, city) => {
	try {
		if (unionId) {
			let wxPubUser = await dbHelper.getOne("t3ds-wx-pub-user", {
				unionId: unionId,
				city
			})
			if (wxPubUser) {
				return wxPubUser.openId
			}
		}
	} catch (e) {
		console.log("获取公众号用户openId遇到错误", e);
	}
}

const getAccount = async (userId, transaction) => {
	try {
		var account = await dbHelper.getOne("t3ds-account", {
			userId: userId
		})
		account = await dbHelper.getById("t3ds-account", account._id, transaction)
		return account;
	} catch (e) {
		throw e;
	}
}

const addAccountLog = async (account, userId, orderId, income, tradeType, handleMan, settled, transaction) => {
	try {
		let accountLog = {
			accountId: account._id,
			userId: userId,
			total: account.total,
			balance: account.balance,
			settle: account.settle,
			frozen: account.frozen,
			income: income,
			tradeType: tradeType,
			orderId: orderId,
			settled: settled,
			createTime: Date.now(),
			createBy: handleMan || "系统"
		}
		await transaction.collection("t3ds-account-log").add(accountLog);
	} catch (e) {
		throw e;
	}
}

const getUser = async (userId, transaction) => {
	try {
		let user = await dbHelper.getOne("uni-id-users", {
			id: parseInt(userId),
			role: 'member'
		})
		if (user) {
			return await dbHelper.getById("uni-id-users", user._id)
		}
	} catch (e) {
		throw e;
	}
}

const getShareExpertGrade = async (value) => {
	try {
		return dbHelper.getOne("t3ds-share-expert-grade", {
			value: value
		})
	} catch (e) {
		throw e;
	}
}

const getShareRelationByUserId = async (userId, transaction) => {
	try {
		var relation = await dbHelper.getOne("t3ds-share-expert-relation", {
			userId: userId
		})
		if (relation) {
			return await dbHelper.getById("t3ds-share-expert-relation", relation._id, transaction)
		}
	} catch (e) {
		throw e;
	}
}

const getShareRelationById = async (id) => {
	try {
		let res = await db.collection("t3ds-share-expert-relation").where({
			_id: id
		}).get();
		if (res.data.length) {
			return res.data[0];
		}
	} catch (e) {
		throw e;
	}
}

const updateAccount = async (account, handleMan, transaction) => {
	try {
		let t = Object.assign({}, account);
		delete t._id;
		t.updateTime = Date.now();
		t.updateBy = handleMan || "";
		console.log("更新账户开始", account)
		await transaction.collection("t3ds-account").doc(account._id).update(t);
		console.log("更新账户完成", account)
	} catch (e) {
		throw e;
	}
}

const calcBrokerage = (profit, level, expertGrade, temporary) => {
	let brokerage;
	if (level == 1) {
		let percent = temporary ? expertGrade.first_percent_tmp : expertGrade.first_percent;
		brokerage = profit * percent / 100;
	} else {
		let percent = temporary ? expertGrade.second_percent_tmp : expertGrade.second_percent;
		brokerage = profit * percent / 100;
	}
	return Math.round(brokerage);
}

const pushIncome = (openId, income, dic) => {
	let list = dic[openId];
	if (!list) {
		list = [];
		dic[openId] = list;
	}
	list.push(income);
}

module.exports = {
	handleOrderPaid: async function(orderId, payTime) {
		let transaction = await db.startTransaction()
		try {
			let order = await dbHelper.getById("t3ds-order", orderId, transaction)
			console.log("handleOrderPaid => order: ", order);
			if (order.status > 1) {
				console.log('订单状态>1退出函数');
				await transaction.commit()
				return
			}
			let user = await dbHelper.getById("uni-id-users", order.user_id, transaction)
			switch (order.type) {
				case 'goods': // 商品订单
					await this.handleGoodsOrderPaid(order, user, transaction)
					break
				case 'subscribe': // 剧本杀预约订单
				case 'renewal': // 续时订单
					await this.handleSubscribeScriptOrderPaid(order, user, transaction)
					break
				case 'tearoom': // 茶室订单
					await this.handleTearoomOrderPaid(order, user, transaction)
					break
				case 'openVip': // 开通会员订单
					await this.handleOpenVipOrderPaid(order, user, transaction)
					break
				case 'recharge': // 充值订单
					await this.handleRechargeOrderPaid(order, user, transaction)
					break
				case 'rent': // 物品租借订单
					await this.handleRentOrderPaid(order, user, transaction)
					break
			}
			await transaction.collection("t3ds-order").doc(orderId).update({
				pay_time: payTime || Date.now()
			})
			await transaction.commit()
		} catch (e) {
			await transaction.rollback()
			console.error('处理已支付订单遇到错误', e)
			throw e
		}
	},

	checkRoomLocked: async function(roomId, startTime, endTime) {
		try {
			let res = await dbHelper.getById("t3ds-store-room", roomId)
			let res1 = await dbHelper.getList("t3ds-store-room", {
				storeId: res.storeId,
				name_number: res.name_number
			})
			let physicalRoom = {
				gameroomId: '',
				tearoomId: ''
			}
			for (let item of res1) {
				switch (item.type) {
					case 'gameroom':
						physicalRoom.gameroomId = item._id
						break;
					case 'tearoom':
						physicalRoom.tearoomId = item._id
						break;
					default:
						break;
				}
			}
			console.log("physicalRoom: ", physicalRoom);

			// 剧本杀
			let motorcadeCount = await db.collection("t3ds-subscribe-motorcade").where({
				'status': dbCmd.in([1, 2, 3, 4, -2]),
				'roomId': physicalRoom.gameroomId,
				'startTime': dbCmd.lt(endTime),
				'endTime': dbCmd.gt(startTime)
			}).count()
			// 茶室
			let teaCount = await db.collection('t3ds-order').where({
				'status': dbCmd.eq(3),
				['items.' + 0 + '.room_id']: physicalRoom.tearoomId,
				['items.' + 0 + '.start_time']: dbCmd.lt(endTime),
				['items.' + 0 + '.end_time']: dbCmd.gt(startTime)
			}).count()
			console.log("是否锁房间: ", motorcadeCount.total > 0 || teaCount.total > 0, motorcadeCount.total,
				teaCount.total);
			return motorcadeCount.total > 0 || teaCount.total > 0
		} catch (e) {
			throw e
		}
	},

	takeUpRoom: async function(motorcade, transaction) {
		try {
			let motorcades = await dbHelper.getList("t3ds-subscribe-motorcade", {
				roomId: motorcade.roomId,
				status: 0,
				_id: dbCmd.neq(motorcade._id),
				startTime: dbCmd.lt(motorcade.endTime),
				endTime: dbCmd.gt(motorcade.startTime)
			})
			if (motorcades.length) {
				for (var i = 0; i < motorcades.length; i++) {
					let motor = motorcades[i]
					await this.cancelMotorcade({
						motorcade: motor,
						serviceCharge: 0,
						handleMan: '系统',
						reason: '房间已被其他用户预定',
						transaction
					})
				}
			}
		} catch (e) {
			throw e
		}
	},

	cancelMotorcade: async function({
		motorcade,
		reason,
		serviceChargeRate = 0,
		handleMan = '系统',
		transaction
	}) {
		try {
			let orders = await dbHelper.getList("t3ds-order", {
				_id: dbCmd.in(motorcade.orderIds)
			})
			for (var i = 0; i < orders.length; i++) {
				let order = orders[i]
				await this.refundNow({
					order,
					reason,
					serviceChargeRate, //退款手续费比例，0表示无手续费，1表示全扣
					transaction
				})
				// 发送预约失败通知
				let user = await dbHelper.getById("uni-id-users", order.user_id, transaction)
				await sendSubscribeNotice(user, order, motorcade, '请重新预定', '预约失败通知')
			}
			let logs = motorcade.operationLogs || []
			logs.unshift({
				action: '取消车队',
				time: Date.now(),
				createBy: handleMan
			})
			if (motorcade.status > 0 && motorcade.roomId) {
				await dbHelper.update("t3ds-store-room", {
					_id: motorcade.roomId,
					status: 0
				}, transaction)
			}
			await dbHelper.update("t3ds-subscribe-motorcade", {
				_id: motorcade._id,
				status: -1,
				cancelReason: reason,
				operationLogs: logs,
				cancelTime: Date.now()
			}, transaction)
			//todo通知用户
		} catch (e) {
			throw e
		}
	},

	handleSubscribeScriptOrderPaid: async function(order, user, transaction) {
		try {
			let orderItem = order.items[0]

			let room = {}
			let store = {}
			if (orderItem.room_id) {
				room = await dbHelper.getById("t3ds-store-room", orderItem.room_id, transaction)
				let roomLocked = await this.checkRoomLocked(room._id, orderItem.start_time, orderItem.end_time)
				if (roomLocked && order.type != 'renewal') {
					//房间被锁定，发起退款
					await this.refundNow({
						order,
						reason: "房间已被其他用户锁定",
						transaction
					})
					// 发送预约失败通知
					if (order.motorcadeId) {
						let motorcade = await dbHelper.getById("t3ds-subscribe-motorcade", order.motorcadeId,
							transaction)
						await sendSubscribeNotice(user, order, motorcade, '请重新预定', '预约失败通知')
					}
					return
				}
				store = await dbHelper.getById("t3ds-store", room.storeId, transaction)
			} else {
				store = await dbHelper.getById("t3ds-store", orderItem.store_id, transaction)
			}

			if (orderItem.script_id) { // 剧本杀订单 + 剧本杀续时订单
				let script = await dbHelper.getById("t3ds-script", orderItem.script_id)
				let motorcade = {}
				if (order.motorcadeId) {
					if (order.type == 'subscribe') {
						console.log('用户加入车队');
						//用户加入车队
						motorcade = await dbHelper.getById("t3ds-subscribe-motorcade", order.motorcadeId,
							transaction)
						let currentMaleCount = motorcade.currentMaleCount + orderItem.maleCount
						let currentFemaleCount = motorcade.currentFemaleCount + orderItem.femaleCount
						if ((currentMaleCount + currentFemaleCount) > script.limitPlayers) {
							//人数超限，发起退款
							await this.refundNow({
								order,
								reason: "人数超限了",
								transaction
							})
							//todo 发送通知
							return
						}
						let status = 0
						if (motorcade.allowGetOn) {
							status = (currentMaleCount + currentFemaleCount) < script.limitPlayers ? 0 : 1
						} else {
							status = (currentMaleCount + currentFemaleCount) < script.minPlayers ? 0 : 1
						}
						let motorcadeStatus = status
						if (status == 1 && store.cooperationMode == 'merchant') { // 人满且是合作门店
							motorcadeStatus = 2
						}
						motorcade.orderIds.push(order._id)
						await dbHelper.update("t3ds-subscribe-motorcade", {
							_id: motorcade._id,
							currentMaleCount,
							currentFemaleCount,
							orderIds: motorcade.orderIds,
							status: motorcadeStatus,
							constituteTime: Date.now()
						}, transaction)
						motorcade.currentMaleCount = currentMaleCount
						motorcade.currentFemaleCount = currentFemaleCount
						motorcade.status = status

						// 修改订单状态
						if (status == 1) { // 车队人数已满
							for (let item of motorcade.orderIds) {
								let {
									doc: orderRes
								} = await transaction.collection('t3ds-order').where({
									_id: item
								}).updateAndReturn({
									status: 3
								})
								// 发送预约通知
								await sendSubscribeNotice(user, order, motorcade, '车队预约成功请准时到店！', '预约成功通知')

								// 拼车成功分享人获得分销佣金
								let userRes = await dbHelper.getById("uni-id-users", orderRes.user_id)
								if (orderRes.shareManId && orderRes.shareManId != userRes.id) {
									console.log("分销佣金before: ", orderRes.shareManId, userRes.id);
									await this.handleSubscribeDistribution(user, orderRes, store.uid, transaction)
								}
							}
						} else {
							await transaction.collection('t3ds-order').doc(order._id).update({
								status: 2
							})
							// 发送预约通知
							await sendSubscribeNotice(user, order, motorcade, '加入车队成功', '预约状态更新通知')
						}
					}
					if (order.type == 'renewal') {
						console.log('用户续时');
						motorcade = await dbHelper.getById("t3ds-subscribe-motorcade", order.motorcadeId,
							transaction)

						await dbHelper.update("t3ds-subscribe-motorcade", {
							_id: motorcade._id,
							renewalOrders: motorcade.renewalOrders
						}, transaction)

						// 修改订单状态
						await transaction.collection('t3ds-order').doc(order._id).update({
							status: 2
						})

						// 发送续时通知
						if (motorcade.compereId) {
							let dmUser = await dbHelper.getById("uni-id-users", motorcade.compereId)
							await sendSubscribeNotice(dmUser, order, motorcade, '车队续时成功', '预约状态更新通知')
						} else {
							console.warn('车队尚未分配主持人，车队id: ', motorcade._id)
						}
					}
				} else {
					console.log('用户发起车队');
					//用户发起车队
					let user = await dbHelper.getById("uni-id-users", order.user_id)

					let time = Math.round((orderItem.end_time - orderItem.start_time) / oneHourInMills)
					let pricePerHour = script.price / script.playTime
					let pricePerPerson = pricePerHour * time + (room.price || store.unifyPrice || 0) * time
					console.log("store: ", store);

					let motorcadeStatus = 0
					if (motorcade.allowGetOn) {
						motorcadeStatus = (orderItem.maleCount + orderItem.femaleCount) < script.limitPlayers ?
							0 : 1
					} else {
						motorcadeStatus = (orderItem.maleCount + orderItem.femaleCount) < script.minPlayers ?
							0 : 1
					}
					if (motorcadeStatus == 1 && store.cooperationMode == 'merchant') { // 人满且是合作门店
						motorcadeStatus = 2
					}
					motorcade = {
						type: 'script',
						scriptId: orderItem.script_id,
						orderIds: [order._id],
						startTime: orderItem.start_time,
						endTime: orderItem.end_time,
						initiator: user.id,
						costPerPerson: pricePerPerson,
						address: store.address,
						location: store.location,
						thumbnail: script.cover,
						name: script.name,
						storeId: store._id,
						storeName: store.name,
						city: store.region.city.value,
						maxPlayers: script.limitPlayers,
						currentMaleCount: orderItem.maleCount,
						currentFemaleCount: orderItem.femaleCount,
						minPlayers: script.minPlayers,
						allowGetOn: order.allowGetOn,
						status: motorcadeStatus,
						createBy: user.nickname || '微信用户',
						createTime: Date.now(),
						renewalOrders: [],
						city_district_id: store.region.area.value // 车队的门店所在行政区划代码
					}
					if (orderItem.room_id) {
						motorcade.roomId = orderItem.room_id
						motorcade.roomName = room.name
					}
					await dbHelper.insert("t3ds-subscribe-motorcade", motorcade, transaction)
					console.log("motorcade: ", motorcade);
					console.log("order: ", order);
					await dbHelper.update("t3ds-order", {
						_id: order._id,
						motorcadeId: motorcade._id,
						updateTime: Date.now(),
						updateBy: user.nickname || '微信用户'
					}, transaction)
					if (orderItem.maleCount + orderItem.femaleCount < script.limitPlayers) { // 当前人数 < 剧本人数上限
						await transaction.collection('t3ds-order').doc(order._id).update({
							status: 2
						})
						console.log('发起车队成功通知');
						// 发送预约通知
						await sendSubscribeNotice(user, order, motorcade, '发起车队成功', '预约状态更新')
					} else {
						let {
							doc: orderRes
						} = await transaction.collection('t3ds-order').where({
							_id: order._id
						}).updateAndReturn({
							status: 3
						})
						console.log('预约成功通知');
						// 发送预约通知
						await sendSubscribeNotice(user, order, motorcade, '车队预约成功请准时到店！', '预约成功通知')

						// 拼车成功分享人获得分销佣金
						if (orderRes.shareManId && orderRes.shareManId != user.id) {
							console.log("分销佣金before: ", orderRes.shareManId, user.id);
							await this.handleSubscribeDistribution(user, orderRes, store.uid, transaction)
						}
					}
				}

				// 占用房间
				if ((motorcade.currentFemaleCount + motorcade.currentMaleCount) >= script.minPlayers &&
					motorcade.roomId) {
					await this.takeUpRoom(motorcade, transaction)
				}
			} else { // 茶室续时订单
				console.log('茶室用户续时');

				// 修改订单状态
				await transaction.collection('t3ds-order').doc(order._id).update({
					status: 3
				})
				let tearoomOrderRes = await dbHelper.getById("t3ds-order", order.tearoomOrderId, transaction)
				await transaction.collection('t3ds-order').doc(order.tearoomOrderId).update({
					['items.' + 0 + '.end_time']: tearoomOrderRes.renewalOrders[0].renewalEndTime,
					['renewalOrders.' + 0]: {
						notPaidInFull: false
					}
				})

				// 发送续时通知
				// let userRes = await dbHelper.getById("uni-id-users", order._id)
				// sendSubscribeNotice(userRes, order, motorcade, '茶室续时成功', '预约状态更新通知')
			}

			// 扣除余额
			var account = await dbHelper.getOne("t3ds-account", {
				userId: user._id
			})
			if (order.use_balance) {
				let b = order.total_fee - order.payment_fee - (order.discount_fee || 0);
				await transaction.collection("t3ds-account").doc(account._id).update({
					total: dbCmd.inc(-b),
					frozen: dbCmd.inc(-b),
					updateTime: Date.now()
				})
				account = await dbHelper.getById("t3ds-account", account._id, transaction)
				await transaction.collection("t3ds-account-log").add({
					userId: user._id,
					accountId: account._id,
					total: account.total,
					income: b,
					tradeType: -1,
					orderId: order._id,
					settled: true,
					createTime: Date.now(),
					createBy: '系统'
				});
				// 更新优惠券使用记录
				if (order.couponId) {
					await transaction.collection('t3ds-coupon-member').doc(order.couponId).update({
						used: true,
						usedTime: Date.now(),
						updateTime: Date.now(),
						updateBy: user.nickname || user.username
					});
				}
			}

			if (order.type != 'renewal') {
				try {
					let merchant = await dbHelper.getById("uni-id-users", store.uid)
					// 超管，共享超管，区域管理员，共享区管
					let admins = await dbHelper.getList("uni-id-users", dbCmd.or([{
							role: dbCmd.or(dbCmd.eq('admin'), dbCmd.eq('share_mgr'))
						},
						{
							role: dbCmd.eq('region_mgr').or(dbCmd.eq('share_region_mgr')),
							city: merchant.city
						}
					]))
					// 老板
					admins.push(merchant)
					for (var i = 0; i < admins.length; i++) {
						let service = admins[i]
						if (service.merchant_info && service.merchant_info.wx_unionid) {
							let openId = await getOpenId(service.merchant_info.wx_unionid, merchant.city)
							if (openId) {
								let temp = await dbHelper.getOne('t3ds-region', {
									'city.value': merchant.city
								})
								let tempId = temp.templateMsgs.find(item => {
									return item.templateName == '新订单通知'
								}).templateID
								let msg = createNewOrderMsg(openId, order, user, tempId);
								await wxPubApi.sendTemplateMsg(merchant.city, msg);
							} else {
								console.warn('用户未绑定微信，无法发送通知，用户id：', service.id)
							}
						} else {
							console.warn('用户未绑定微信，无法发送通知，用户id', service.id)
						}
					}
				} catch (e) {
					console.error('发送新订单通知遇到错误', e)
				}
			}
		} catch (e) {
			console.error(e)
			throw e
		}
	},

	// 茶室订单
	handleTearoomOrderPaid: async function(order, user, transaction) {
		try {
			let orderItem = order.items[0]

			let room = await dbHelper.getById("t3ds-store-room", orderItem.room_id, transaction)
			let store = await dbHelper.getById("t3ds-store", room.storeId, transaction)

			// 扣除余额
			var account = await dbHelper.getOne("t3ds-account", {
				userId: user._id
			})
			if (order.use_balance) {
				let b = order.total_fee - order.payment_fee - (order.discount_fee || 0);
				await transaction.collection("t3ds-account").doc(account._id).update({
					total: dbCmd.inc(-b),
					frozen: dbCmd.inc(-b),
					updateTime: Date.now()
				})
				account = await dbHelper.getById("t3ds-account", account._id, transaction)
				await transaction.collection("t3ds-account-log").add({
					userId: user._id,
					accountId: account._id,
					total: account.total,
					income: b,
					tradeType: -1,
					orderId: order._id,
					settled: true,
					createTime: Date.now(),
					createBy: '系统'
				});
				// 更新优惠券使用记录
				if (order.couponId) {
					await transaction.collection('t3ds-coupon-member').doc(order.couponId).update({
						used: true,
						usedTime: Date.now(),
						updateTime: Date.now(),
						updateBy: user.nickname || user.username
					});
				}
			}

			await transaction.collection('t3ds-order').doc(order._id).update({
				status: 3
			})

			// 发送新订单通知
			try {
				// admin boss
				let merchant = await dbHelper.getById("uni-id-users", store.uid)
				let admins = await dbHelper.getList("uni-id-users", dbCmd.or([{
					role: dbCmd.eq('admin')
				}, {
					// role: dbCmd.eq('boss')),
					// city: merchant.city,
					_id: dbCmd.eq(merchant._id)
				}]))
				console.log("admins: ", admins);
				for (var i = 0; i < admins.length; i++) {
					let service = admins[i]
					if (service.merchant_info && service.merchant_info.wx_unionid) {
						let openId = await getOpenId(service.merchant_info.wx_unionid, merchant.city)
						if (openId) {
							let temp = await dbHelper.getOne('t3ds-region', {
								'city.value': merchant.city
							})
							let tempId = temp.templateMsgs.find(item => {
								return item.templateName == '新订单通知'
							}).templateID
							let msg = createNewOrderMsg(openId, order, user, tempId);
							await wxPubApi.sendTemplateMsg(merchant.city, msg);
						} else {
							console.warn('用户未绑定微信，无法发送通知，用户id：', service.id)
						}
					} else {
						console.warn('用户未绑定微信，无法发送通知，用户id', service.id)
					}
				}
			} catch (e) {
				console.error('发送新订单通知遇到错误', e)
			}
		} catch (e) {
			console.error(e)
			throw e
		}
	},

	handleGoodsOrderPaid: async function(order, user, transaction) {
		try {
			let orderItem = order.items[0]
			let goods = await dbHelper.getById("t3ds-mall-goods", orderItem.goods_id, transaction)
			let merchant = await dbHelper.getById("uni-id-users", goods.uid)
			let sku = await dbHelper.getById("t3ds-mall-sku", orderItem.sku_id, transaction)
			if (goods.type == 'ticket') {
				// 扣除余额
				var account = await dbHelper.getOne("t3ds-account", {
					userId: user._id
				})
				if (order.use_balance) {
					let b = order.total_fee - order.payment_fee;
					await transaction.collection("t3ds-account").doc(account._id).update({
						total: dbCmd.inc(-b),
						frozen: dbCmd.inc(-b),
						updateTime: Date.now()
					})
					account = await dbHelper.getById("t3ds-account", account._id, transaction)
					await transaction.collection("t3ds-account-log").add({
						userId: user._id,
						accountId: account._id,
						total: account.total,
						settle: account.settle,
						balance: account.balance,
						frozen: account.frozen,
						income: b,
						tradeType: -1,
						orderId: order._id,
						settled: true,
						createTime: Date.now(),
						createBy: '系统'
					});
				}

				if (!goods.channel || goods.channel == 'self') {
					// 生成票券
					let deadline;
					if (sku.time_limit) {
						if (sku.time_limit.type == 'relative') {
							deadline = moment().tz("Asia/Shanghai").add(sku.time_limit.value, 'days').hour(23)
								.minute(59).second(59).toDate()
								.getTime() //Date.now() + sku.time_limit.value * 24 * 60 * 60 * 1000
						} else {
							deadline = moment.tz(sku.time_limit.value, "Asia/Shanghai").hour(23).minute(59)
								.second(59).toDate().getTime();
						}
					} else {
						deadline = moment().tz("Asia/Shanghai").add(30, 'days').hour(23).minute(59).second(59)
							.toDate().getTime();
					}
					let totalCount = await dbHelper.getCount("t3ds-ticket-code", {})
					for (var i = 0; i < orderItem.count; i++) {
						let ticketCode = {
							orderId: order._id,
							deadline: deadline,
							status: 0,
							goodsPrice: orderItem.price,
							settlementPrice: orderItem.settlement_price,
							sn: `10${user.id}${totalCount + i + 1}`
						}
						if (orderItem.sku_name) {
							ticketCode.goodsName = `${orderItem.goods_name}|${orderItem.sku_name}`;
						} else {
							ticketCode.goodsName = orderItem.goods_name;
						}
						await transaction.collection("t3ds-ticket-code").add(ticketCode);
					}
				}
				// 处理分销佣金
				if (goods.distribution && (!goods.channel || goods.channel == 'self')) {
					await this.handleDistribution(order, goods, merchant, sku, account, user, transaction)
				}
				if (!goods.channel || goods.channel == 'self') {
					await transaction.collection('t3ds-order').doc(order._id).update({
						status: 3
					})
				} else {
					await transaction.collection('t3ds-order').doc(order._id).update({
						status: 2
					})
				}
			} else if (goods.type == 'vipCard') {
				let vipCard = await dbHelper.getById("t3ds-vip-card", sku.vip_card_id, transaction)
				await this.updateUserVipInfo(vipCard, user, transaction)

				await transaction.collection('t3ds-order').doc(order._id).update({
					status: 5
				})
			}
			try {
				var admins = []
				// 系统管理员
				// 区域管理员
				// 渠道客服
				if (order.channel && order.channel != 'self') {
					admins = await dbHelper.getList("uni-id-users", dbCmd.or([{
						role: dbCmd.eq('admin')
					}, {
						role: dbCmd.eq('channel_service').or(dbCmd.eq("region_mgr")),
						city: merchant.city
					}]))
				} else {
					admins = await dbHelper.getList("uni-id-users", dbCmd.or([{
						role: dbCmd.eq('admin')
					}, {
						role: dbCmd.eq('region_mgr'),
						city: merchant.city
					}]))
				}
				for (var i = 0; i < admins.length; i++) {
					let service = admins[i]
					if (service.merchant_info && service.merchant_info.wx_unionid) {
						let openId = await getOpenId(service.merchant_info.wx_unionid, merchant.city)
						if (openId) {
							let temp = await dbHelper.getOne('t3ds-region', {
								'city.value': merchant.city
							})
							let tempId = temp.templateMsgs.find(item => {
								return item.templateName == '新订单通知'
							}).templateID
							let msg = createNewOrderMsg(openId, order, user, tempId);
							await wxPubApi.sendTemplateMsg(merchant.city, msg);
						} else {
							console.warn('用户未绑定微信，无法发送通知，用户id：', service.id)
						}
					} else {
						console.warn('用户未绑定微信，无法发送通知，用户id', service.id)
					}
				}
			} catch (e) {
				console.error('发送新订单通知遇到错误', e)
			}
		} catch (e) {
			throw e
		}
	},

	handleDistribution: async function(order, goods, merchant, sku, buyManAccount, buyMan, transaction) {
		let shareManAccount,
			shareManOrder,
			shareManRelation,
			shareMan,
			buyManRelation,
			buyManOrder,
			//分销者的上级和上上级
			firstManAccount,
			firstManRelation,
			firstMan,
			firstManOrder,
			secondManAccount,
			secondManRelation,
			secondMan,
			secondManOrder,
			//分享者的上级和上上级
			firstManAccount2,
			firstManRelation2,
			firstMan2,
			firstManOrder2,
			secondManAccount2,
			secondManRelation2,
			secondMan2,
			secondManOrder2;

		// 收益字典，用于创建模板消息
		let incomes = {};
		let handleMan = '系统'
		try {
			let shareOrderTemplate = {
				orderId: order._id,
				buyManId: order.user_id,
				buyManGrade: buyMan.shareGrade,
				createTime: Date.now(),
				createBy: handleMan
			}

			buyManOrder = Object.assign({}, shareOrderTemplate);
			buyManOrder.userId = order.user_id;

			if (order.shareManId && order.shareManId != buyMan.id) {
				shareMan = await getUser(order.shareManId, transaction);
				if (shareMan) {
					shareManAccount = await getAccount(shareMan._id, transaction);
					shareManOrder = Object.assign({}, shareOrderTemplate);
					shareManOrder.userId = shareMan._id;
					shareManRelation = await getShareRelationByUserId(shareMan._id, transaction);

					if (shareManRelation && shareManRelation.parentId) {
						firstManRelation2 = await dbHelper.getById("t3ds-share-expert-relation",
							shareManRelation.parentId, transaction)
						if (firstManRelation2) {
							firstManAccount2 = await getAccount(firstManRelation2.userId, transaction);
							firstMan2 = await dbHelper.getById("uni-id-users", firstManRelation2.userId,
								transaction)
							firstManOrder2 = Object.assign({}, shareOrderTemplate);
							firstManOrder2.userId = firstManRelation2.userId;

							if (firstManRelation2.parentId) {
								secondManRelation2 = await dbHelper.getById("t3ds-share-expert-relation",
									firstManRelation2.parentId, transaction)
								if (secondManRelation2) {
									secondManAccount2 = await getAccount(secondManRelation2.userId,
										transaction);
									secondMan2 = await dbHelper.getById("uni-id-users", secondManRelation2
										.userId, transaction)
									secondManOrder2 = Object.assign({}, shareOrderTemplate);
									secondManOrder2.userId = secondManRelation2.userId;
								}
							}
						}
					}
				}
			}
			buyManRelation = await getShareRelationByUserId(order.user_id, transaction);
			if (buyManRelation && buyManRelation.parentId) {
				firstManRelation = await dbHelper.getById("t3ds-share-expert-relation", buyManRelation.parentId,
					transaction)
				if (firstManRelation) {
					firstMan = await dbHelper.getById("uni-id-users", firstManRelation.userId, transaction)
					if (shareMan && firstManRelation.userId == shareMan._id) {
						firstManAccount = shareManAccount;
						firstManOrder = shareManOrder;
					} else if (firstManRelation2 && firstManRelation.userId == firstManRelation2.userId) {
						firstManAccount = firstManAccount2;
						firstManOrder = firstManOrder2;
					} else if (secondManRelation2 && firstManRelation.userId == secondManRelation2.userId) {
						firstManAccount = secondManAccount2;
						firstManOrder = secondManOrder2;
					} else {
						firstManAccount = await getAccount(firstManRelation.userId, transaction);
						firstManOrder = Object.assign({}, shareOrderTemplate);
						firstManOrder.userId = firstManRelation.userId;
					}
					if (firstManRelation.parentId) {
						secondManRelation = await dbHelper.getById("t3ds-share-expert-relation",
							firstManRelation.parentId, transaction)
						if (secondManRelation) {
							secondMan = await dbHelper.getById("uni-id-users", secondManRelation.userId,
								transaction)
							if (shareMan && secondManRelation.userId == shareMan._id) {
								secondManAccount = shareManAccount;
								secondManOrder = shareManOrder;
							} else if (firstManRelation2 && secondManRelation.userId == firstManRelation2
								.userId) {
								secondManAccount = firstManAccount2;
								secondManOrder = firstManOrder2;
							} else if (secondManRelation2 && secondManRelation.userId == secondManRelation2
								.userId) {
								secondManAccount = secondManAccount2;
								secondManOrder = secondManOrder2;
							} else {
								secondManAccount = await getAccount(secondManRelation.userId, transaction);
								secondManOrder = Object.assign({}, shareOrderTemplate);
								secondManOrder.userId = secondManRelation.userId;
							}
						}
					}
				}
			}
			//总利润
			let profit = order.total_fee - sku.settlement_price * order.items[0].count;
			console.log("总利润", profit + '');

			if (profit <= 0) {
				shareManOrder = null;
				firstManOrder = null;
				secondManOrder = null;
				firstManOrder2 = null;
				secondManOrder2 = null;
			}
			//计算收益（分享者奖励、返现、分销返佣）
			//计算分享者奖励
			if (profit > 0 && shareMan && shareMan._id != order.user_id) {
				let gradeSetting = await getShareExpertGrade(shareMan.shareGrade);
				// var shareRewardPercent;
				let shareReward;

				if (buyManRelation) {
					//分享给有上下级关系的用户（即老用户）
					if (buyMan.shareGrade > 0) {
						console.log("分享给达人")
						// 分享给达人
						if (sku.share_reward3 != undefined && sku.share_reward3 >= 0) {
							shareReward = Math.round(sku.share_reward3 / 100 * profit);
							if (shareReward < 100 && sku.share_reward3 > 0) {
								shareReward = 100
							}
						} else {
							shareReward = Math.round(gradeSetting.share_reward3 / 100 * profit);
							if (shareReward < 100 && gradeSetting.share_reward3 > 0) {
								shareReward = 100
							}
						}
					} else {
						console.log("分享给非达人")
						// 分享给非达人
						let ratio;
						if (sku.share_reward_old) {
							ratio = sku.share_reward_old[shareMan.shareGrade + '']
						}
						if (!ratio || ratio < 0) {
							ratio = gradeSetting.share_reward2
						}
						shareReward = Math.round(ratio / 100 * profit)
						if (shareReward < 100 && ratio > 0) {
							shareReward = 100
						}
					}
				} else {
					//分享给没有上下级关系的用户，即新用户
					let shareRewardPercent = sku.share_reward[shareMan.shareGrade + ''];
					if (shareRewardPercent != undefined && shareRewardPercent >= 0) {
						shareReward = Math.round(shareRewardPercent / 100 * profit);
						if (shareReward < 100 && shareRewardPercent > 0) {
							shareReward = 100
						}
					} else {
						shareReward = Math.round(gradeSetting.share_reward / 100 * profit);
						if (shareReward < 100 && gradeSetting.share_reward > 0) {
							shareReward = 100
						}
					}
					// if (!shareRewardPercent) {
					// 	shareRewardPercent = gradeSetting.share_reward;
					// }
				}
				// var shareReward = Math.round(shareRewardPercent / 100 * profit);
				// if (shareReward < 100) {
				// 	shareReward = 100
				// }
				if (shareReward > 0) {
					shareManAccount.total += shareReward;
					if (!sku.settle_chance) {
						shareManAccount.balance += shareReward;
					} else {
						shareManAccount.settle += shareReward;
					}
					shareManOrder.shareReward = shareReward;
					await addAccountLog(shareManAccount, shareMan._id, order._id, shareReward, 1, handleMan,
						!sku.settle_chance, transaction);

					//更新最近一次获得收益的时间
					await transaction.collection("uni-id-users").doc(shareMan._id).update({
						latestIncomeTime: Date.now()
					})

					let shareManOpenId = await getOpenId(shareMan.wx_unionid, merchant.city);
					if (shareManOpenId) {
						pushIncome(shareManOpenId, {
							type: "分享收益",
							value: shareReward,
							// subTitle: `您分享商品给（${buyMan.nickname || ('ID: ' + buyMan.id)}）获取了佣金收益！`
							shareMan: shareMan ? shareMan.nickname || shareMan.id : false
						}, incomes);
					} else {
						console.warn(`用户${order.shareManId}没有关注公众号，无法发送通知`)
					}

					//计算分享者上级和上上级佣金
					if (firstManRelation2) {
						//分享给新用户和老用户配置不一样
						let firstShareMan = await dbHelper.getById("uni-id-users", firstManRelation2.userId,
							transaction)
						if (firstShareMan) {
							let firstGradeSetting = await getShareExpertGrade(firstShareMan.shareGrade);
							let p1 = buyManRelation ? firstGradeSetting.first_share_reward_percent_2 :
								firstGradeSetting.first_share_reward_percent;
							let firstShareBrokerage = Math.round(p1 / 100 * shareReward);
							if (firstShareBrokerage > 0) {
								firstManAccount2.total += firstShareBrokerage;
								if (!sku.settle_chance) {
									firstManAccount2.balance += firstShareBrokerage;
								} else {
									firstManAccount2.settle += firstShareBrokerage;
								}
								firstManOrder2.firstShareBrokerage = firstShareBrokerage;
								await addAccountLog(firstManAccount2, firstMan2._id, order._id,
									firstShareBrokerage, 7, handleMan, !sku.settle_chance, transaction);

								let firstManOpenId = await getOpenId(firstMan2.wx_unionid, merchant.city);
								if (firstManOpenId) {
									pushIncome(firstManOpenId, {
										type: "团队一级分享佣金",
										value: firstShareBrokerage,
										// subTitle: `您团队的（${shareMan.nickname || ('ID: ' + shareMan.id)}）分享商品给（${buyMan.nickname || ('ID: ' + buyMan.id)}）获得了一级分享佣金收益！`
										shareMan: shareMan ? shareMan.nickname || shareMan.id : false
									}, incomes);
								} else {
									console.warn(`用户${order.shareManId}没有关注公众号，无法发送通知`)
								}

								if (secondManRelation2) {
									//分享给新用户和老用户配置不一样
									let secondShareMan = await dbHelper.getById("uni-id-users",
										secondManRelation2.userId, transaction)
									if (secondShareMan) {
										let secondGradeSetting = await getShareExpertGrade(secondShareMan
											.shareGrade);
										let p2 = buyManRelation ? secondGradeSetting
											.second_share_reward_percent_2 : secondGradeSetting
											.second_share_reward_percent;
										let secondShareBrokerage = Math.round(p2 / 100 * shareReward);
										if (secondShareBrokerage > 0) {
											secondManAccount2.total += secondShareBrokerage;
											if (!sku.settle_chance) {
												secondManAccount2.balance += secondShareBrokerage;
											} else {
												secondManAccount2.settle += secondShareBrokerage;
											}
											secondManOrder2.secondShareBrokerage = secondShareBrokerage;
											await addAccountLog(secondManAccount2, secondMan2._id, order._id,
												secondShareBrokerage, 8, handleMan, !sku.settle_chance, transaction);

											let secondManOpenId = await getOpenId(secondMan2.wx_unionid,
												merchant.city);
											if (secondManOpenId) {
												pushIncome(secondManOpenId, {
													type: "团队二级分享佣金",
													value: secondShareBrokerage,
													// subTitle: `您团队的（${shareMan.nickname || ('ID: ' + shareMan.id)}）分享商品给（${buyMan.nickname || ('ID: ' + buyMan.id)}）获得了二级分享佣金收益！`
													shareMan: shareMan ? shareMan.nickname || shareMan
														.id : false
												}, incomes);
											} else {
												console.warn(`用户${order.shareManId}没有关注公众号，无法发送通知`)
											}
										}
									}
								}
							}
						}
					}
				} else {
					shareManOrder = null;
					firstManOrder2 = null;
					secondManOrder2 = null;
				}
			}

			//计算达人返现
			if (profit > 0) {
				if (buyMan.shareGrade != 0) {
					console.log("计算达人返现金额");
					var rewardPercent = sku.self_buy_reward[buyMan.shareGrade];
					if (rewardPercent == undefined || rewardPercent < 0) {
						let gradeSetting = await getShareExpertGrade(buyMan.shareGrade);
						rewardPercent = gradeSetting.self_buy_reward;
					}
					let reward = Math.round(rewardPercent / 100 * profit);
					if (reward > 0) {
						buyManAccount.total += reward;
						if (!goods.channel || goods.channel == 'self') {
							buyManAccount.settle += reward;
							await transaction.collection("t3ds-account").doc(buyManAccount._id).update({
								total: buyManAccount.total,
								settle: buyManAccount.settle,
								updateTime: Date.now(),
								updateBy: handleMan || ""
							})
							await addAccountLog(buyManAccount, buyMan._id, order._id, reward, 2, handleMan,
								false, transaction);
						} else {
							buyManAccount.balance += reward;
							await transaction.collection("t3ds-account").doc(buyManAccount._id).update({
								total: buyManAccount.total,
								balance: buyManAccount.balance,
								updateTime: Date.now(),
								updateBy: handleMan || ""
							})
							await addAccountLog(buyManAccount, buyMan._id, order._id, reward, 2, handleMan,
								true, transaction);
						}

						//更新最近一次获得收益的时间
						await transaction.collection("uni-id-users").doc(buyMan._id).update({
							latestIncomeTime: Date.now()
						})

						buyManOrder.buyReward = reward;
						console.log("buyMan: ", buyMan);
						let buyManOpenId = await getOpenId(buyMan.wx_unionid, merchant.city);
						if (buyManOpenId) {
							pushIncome(buyManOpenId, {
								type: "返现收益",
								value: reward,
								// shareMan: `您分享商品给（${buyMan.nickname || ('ID: ' + buyMan.id)}）获取了佣金收益！`
								shareMan: shareMan ? shareMan.nickname || shareMan.id : false
							}, incomes);
						} else {
							console.warn(`用户${order.user_id}没有关注公众号，无法发送通知`)
						}
					}
				}
			}
			let orderItem = order.items[0]
			//计算上级分销返佣
			// 存在上级
			if (buyManRelation) {
				if (profit > 0 && firstManRelation) {
					console.log("计算一级分佣开始，用户id", firstManRelation.userId);
					var brokerage;
					if (buyMan.shareGrade >= 3) {
						//高级达人的上级佣金固定1元
						brokerage = 100 * orderItem.count;
					} else {
						let expertGrade = await getShareExpertGrade(firstMan.shareGrade);
						brokerage = calcBrokerage(profit, 1, expertGrade, buyManRelation.temporary);
					}
					console.log("计算一级分佣完成", brokerage + "");
					if (brokerage) {
						firstManOrder.firstBrokerage = brokerage;
						firstManAccount.total += brokerage;
						if (!sku.settle_chance) {
							firstManAccount.balance += brokerage;
						} else {
							firstManAccount.settle += brokerage;
						}
						await addAccountLog(firstManAccount, firstMan._id, order._id, brokerage, 3, handleMan,
							!sku.settle_chance, transaction)

						let firstManOpenId = await getOpenId(firstMan.wx_unionid, merchant.city);
						console.log("firstManOpenId: ", firstManOpenId);
						if (firstManOpenId) {
							pushIncome(firstManOpenId, {
								type: "一级团队佣金",
								value: brokerage,
								// subTitle: `您团队的一级达人（${buyMan.nickname || ('ID: ' + buyMan.id)}）下单获取了佣金收益！`
								shareMan: shareMan ? shareMan.nickname || shareMan.id : false
							}, incomes);
						} else {
							console.warn(`用户${firstManRelation.userId}没有关注公众号，无法发送通知`)
						}

						// 存在上上级
						if (secondManRelation) {
							console.log("计算二级分佣开始，用户id", secondManRelation.userId);
							let expertGrade = await getShareExpertGrade(secondMan.shareGrade);
							brokerage = calcBrokerage(profit, 2, expertGrade, buyManRelation.temporary);
							console.log("计算二级分佣完成", brokerage + "");
							if (brokerage) {
								secondManOrder.secondBrokerage = brokerage;
								secondManAccount.total += brokerage;
								if (!sku.settle_chance) {
									secondManAccount.balance += brokerage;
								} else {
									secondManAccount.settle += brokerage;
								}
								await addAccountLog(secondManAccount, secondMan._id, order._id, brokerage, 4,
									handleMan, !sku.settle_chance, transaction)
								let secondManOpenId = await getOpenId(secondMan.wx_unionid, merchant.city);
								if (secondManOpenId) {
									pushIncome(secondManOpenId, {
										type: "二级团队佣金",
										value: brokerage,
										// subTitle: `您团队的二级达人（${buyMan.nickname || ('ID: ' + buyMan.id)}）获取了佣金收益！`
										shareMan: shareMan ? shareMan.nickname || shareMan.id : false
									}, incomes);
								} else {
									console.warn(`用户${secondManRelation.userId}没有关注公众号，无法发送通知`)
								}
							}
						}
					}
				}
				if (buyManRelation.temporary && !buyManRelation.parentId && shareMan && shareMan.id != buyMan
					.id) {
					console.log("建立关系");
					if (!shareManRelation) {
						//分享者不存在临时关系
						shareManRelation = {
							userId: shareMan._id, //order.shareManId,
							temporary: true,
							createTime: Date.now(),
							createBy: handleMan || ""
						}
						await dbHelper.insert("t3ds-share-expert-relation", shareManRelation, transaction)
					}
					await transaction.collection("t3ds-share-expert-relation").doc(buyManRelation._id)
						.update({
							parentId: shareManRelation._id
						});

					// 通知临时团队绑定成功
				}
			} else {
				if (shareMan && shareMan.id != buyMan.id) {
					console.log("建立关系");
					if (!shareManRelation) {
						//分享者不存在临时关系
						shareManRelation = {
							userId: shareMan._id,
							temporary: true,
							createTime: Date.now(),
							createBy: handleMan || ""
						}
						await dbHelper.insert("t3ds-share-expert-relation", shareManRelation, transaction)
					}
					buyManRelation = {
						userId: buyMan._id,
						temporary: true,
						parentId: shareManRelation._id
					}
					await dbHelper.insert("t3ds-share-expert-relation", buyManRelation, transaction)
					// 通知临时团队绑定成功
				}
			}

			if (shareManAccount) {
				console.log("更新分享者账户");
				await updateAccount(shareManAccount, handleMan, transaction)
			}
			if (firstManAccount && (!shareManAccount || shareManAccount._id != firstManAccount._id)) {
				console.log("更新一级用户账户");
				await updateAccount(firstManAccount, handleMan, transaction)
			}
			if (secondManAccount && (!shareManAccount || shareManAccount._id != secondManAccount._id)) {
				console.log("更新二级用户账户");
				await updateAccount(secondManAccount, handleMan, transaction)
			}
			if (firstManAccount2) {
				console.log("更新一级分享用户账户");
				await updateAccount(firstManAccount2, handleMan, transaction)
			}
			if (secondManAccount2) {
				console.log("更新二级分享用户账户");
				await updateAccount(secondManAccount2, handleMan, transaction)
			}
			if (shareManOrder && shareManOrder.shareReward) {
				console.log("创建分享者订单");
				await transaction.collection("t3ds-share-order").add(shareManOrder);
			}
			if (firstManOrder2 && firstManOrder2.firstShareBrokerage) {
				console.log("创建一级分享用户订单");
				await transaction.collection("t3ds-share-order").add(firstManOrder2);
			}
			if (secondManOrder2 && secondManOrder2.secondShareBrokerage) {
				console.log("创建二级分享用户订单");
				await transaction.collection("t3ds-share-order").add(secondManOrder2);
			}
			if (firstManOrder && firstManOrder.firstBrokerage && (!shareManOrder || firstManOrder.userId !=
					shareManOrder.userId) &&
				(!firstManOrder2 || firstManOrder.userId != firstManOrder2.userId) &&
				(!secondManOrder2 || firstManOrder.userId != secondManOrder2.userId)) {
				console.log("创建一级用户订单");
				await transaction.collection("t3ds-share-order").add(firstManOrder);
			}
			if (secondManOrder && secondManOrder.secondBrokerage && (!shareManOrder || secondManOrder.userId !=
					shareManOrder.userId) &&
				(!firstManOrder2 || secondManOrder.userId != firstManOrder2.userId) &&
				(!secondManOrder2 || secondManOrder.userId != secondManOrder2.userId)) {
				console.log("创建二级用户订单");
				await transaction.collection("t3ds-share-order").add(secondManOrder);
			}
			await transaction.collection("t3ds-share-order").add(buyManOrder);
			await transaction.collection("t3ds-order").doc(order._id).update({
				status: 3
			})

			//发送通知
			try {
				console.log("incomes: ", incomes);
				let keys = Object.keys(incomes);
				for (var i = 0; i < keys.length; i++) {
					let key = keys[i]
					let temp = await dbHelper.getOne('t3ds-region', {
						'city.value': merchant.city
					})
					let tempId = temp.templateMsgs.find(item => {
						return item.templateName == '结算成功通知'
					}).templateID
					let msg = createMsg(key, order, incomes[key], tempId);
					await wxPubApi.sendTemplateMsg(merchant.city, msg);
				}
			} catch (e) {
				console.log("发送分销佣金到账通知遇到错误", e.message || '------------');
			}
		} catch (e) {
			throw e
		}
	},

	handleSubscribeDistribution: async function(buyMan, order, storeUid, transaction) {
		try {
			console.log('进入handleSubscribeDistribution');
			let scriptRes = await dbHelper.getById("t3ds-script", order.items[0].script_id, transaction)
			let shareBrokerage = scriptRes.shareBrokerage
			if (!scriptRes.shareBrokerage) {
				let configRes = await dbHelper.getOne("t3ds-system-config", {
					key: 'shareBrokerage'
				}, transaction)
				shareBrokerage = configRes.value / 100
			}
			console.log("计算佣金：", order.total_fee, shareBrokerage);

			let shareMan = await getUser(order.shareManId, transaction);
			let newOrder = {
				orderId: order._id,
				userId: shareMan._id,
				buyManId: order.user_id,
				buyManGrade: buyMan.shareGrade,
				shareReward: order.total_fee * shareBrokerage,
				createBy: '系统',
				createTime: Date.now()
			}
			await transaction.collection("t3ds-share-order").add(newOrder)
			// console.log("shareMan: ", shareMan);
			let accountRes = await getAccount(shareMan._id, transaction)
			accountRes.balance += newOrder.shareReward;
			accountRes.total += newOrder.shareReward;
			await transaction.collection("t3ds-account").doc(accountRes._id).update({
				total: dbCmd.inc(newOrder.shareReward),
				balance: dbCmd.inc(newOrder.shareReward),
				updateTime: Date.now(),
				updateBy: '系统'
			})
			await addAccountLog(accountRes, shareMan._id, order._id, newOrder.shareReward, 1, '系统', true,
				transaction);

			//更新最近一次获得收益的时间
			await transaction.collection("uni-id-users").doc(shareMan._id).update({
				latestIncomeTime: Date.now()
			})

			// 通知
			let merchantRes = await dbHelper.getById("uni-id-users", storeUid, transaction)
			if (shareMan.merchant_info && shareMan.merchant_info.wx_unionid) {
				let openId = await getOpenId(shareMan.merchant_info.wx_unionid, merchantRes.city)
				if (openId) {
					let temp = await dbHelper.getOne('t3ds-region', {
						'city.value': merchantRes.city
					})
					let tempId = temp.templateMsgs.find(item => {
						return item.templateName == '结算成功通知'
					}).templateID
					let incomes = {};
					pushIncome(openId, {
						type: "分享收益",
						value: newOrder.shareReward,
						shareMan: shareMan ? shareMan.nickname || shareMan.id : false
					}, incomes);
					let msg = createMsg(openId, order, incomes[openId], tempId);
					console.log("msg: ", msg);
					await wxPubApi.sendTemplateMsg(merchantRes.city, msg);
				} else {
					console.warn('subscribe，用户未绑定微信，无法发送通知，用户id：', shareMan.id)
				}
			} else {
				console.warn('subscribe，用户未绑定微信，无法发送通知，用户id', shareMan.id)
			}
		} catch (e) {
			throw e
		}
	},

	handleOpenVipOrderPaid: async function(order, user, transaction) {
		try {
			let vipCard = await dbHelper.getById("t3ds-vip-card", order.items[0]._id, transaction)
			await this.updateUserVipInfo(vipCard, user, transaction)
			await transaction.collection('t3ds-order').doc(order._id).update({
				status: 5
			})
		} catch (e) {
			throw e
		}
	},

	handleRechargeOrderPaid: async function(order, user, transaction) {
		try {
			let account = await dbHelper.getOne("t3ds-account", {
				userId: user._id
			})
			await transaction.collection("t3ds-account").doc(account._id).update({
				balance: dbCmd.inc(order.total_fee),
				total: dbCmd.inc(order.total_fee)
			})
			account.balance += order.total_fee
			account.total += order.total_fee
			await addAccountLog(account, user._id, order._id, order.total_fee, 10, '', true, transaction);
			await transaction.collection('t3ds-order').doc(order._id).update({
				status: 5
			})
		} catch (e) {
			throw e
		}
	},

	handleRentOrderPaid: async function(order, user, transaction) {
		try {
			let goods = await dbHelper.getById("t3ds-goods-rent", order.items[0].goods_id)
			let rentHistory = {
				storeId: goods.storeId,
				goodsId: goods._id,
				goodsName: goods.name,
				count: order.items[0].count,
				memberId: user._id,
				memberName: user.nickname,
				orderId: order._id,
				rentTime: Date.now()
			}
			await dbHelper.insert("t3ds-goods-rent-history", rentHistory, transaction)
			await transaction.collection('t3ds-order').doc(order._id).update({
				status: 3
			})
		} catch (e) {
			throw e
		}
	},

	updateUserVipInfo: async function(vipCard, user, transaction) {
		try {
			if (user.vipInfo && user.vipInfo.storeVipCardInfo && vipCard.type == 'store') {
				if (user.vipInfo.storeVipCardInfo.expirationTime > Date.now() &&
					vipCard.level < user.vipInfo.storeVipCardInfo.level) {
					throw new Error('不能兑换比当前卡等级低的卡')
				}
				if (user.vipInfo.storeVipCardInfo.expirationTime > Date.now() &&
					vipCard.settlementWay != user.vipInfo.storeVipCardInfo.settlementWay) {
					throw new Error('不能兑换与当前卡种类不相同的卡')
				}
			}
			if (vipCard.type == 'store') {
				if (user.vipInfo) {
					let time
					if (user.vipInfo.storeVipCardInfo && user.vipInfo.storeVipCardInfo.expirationTime > Date
						.now()) {
						// 未过期
						switch (vipCard.time) {
							case 'oneMonth':
								time = moment(user.vipInfo.storeVipCardInfo.expirationTime).tz("Asia/Shanghai")
									.add(1, 'months').hour(23).minute(59).second(59).toDate().getTime()
								break
							case 'threeMonth':
								time = moment(user.vipInfo.storeVipCardInfo.expirationTime).tz("Asia/Shanghai")
									.add(3, 'months').hour(23).minute(59).second(59).toDate().getTime()
								break
							case 'oneYear':
								time = moment(user.vipInfo.storeVipCardInfo.expirationTime).tz("Asia/Shanghai")
									.add(1, 'years').hour(23).minute(59).second(59).toDate().getTime()
								break
						}
					} else {
						switch (vipCard.time) {
							case 'oneMonth':
								time = moment().tz("Asia/Shanghai").add(1, 'months').hour(23).minute(59).second(
									59).toDate().getTime()
								break
							case 'threeMonth':
								time = moment().tz("Asia/Shanghai").add(3, 'months').hour(23).minute(59).second(
									59).toDate().getTime()
								break
							case 'oneYear':
								time = moment().tz("Asia/Shanghai").add(1, 'years').hour(23).minute(59).second(
									59).toDate().getTime()
								break
						}
					}
					let data = {
						'vipInfo.storeVipCardInfo': {
							cardId: vipCard._id,
							cardImageUrl: vipCard.imageUrl,
							cardName: vipCard.name,
							expirationTime: time,
							settlementWay: vipCard.settlementWay,
							time: vipCard.time,
							level: vipCard.level
						}
					}
					if (vipCard.settlementWay == 'time' && vipCard.time == 'oneYear') {
						data.serviceRemainTimes = {}
					}
					await transaction.collection("uni-id-users").doc(user._id).update(data)
				} else {
					user.vipInfo = {}
					let copyUser = JSON.parse(JSON.stringify(user))
					delete copyUser._id
					await transaction.collection("uni-id-users").doc(user._id).set(copyUser)
					let time
					switch (vipCard.time) {
						case 'oneMonth':
							time = moment().tz("Asia/Shanghai").add(1, 'months').hour(23).minute(59).second(59)
								.toDate().getTime()
							break
						case 'threeMonth':
							time = moment().tz("Asia/Shanghai").add(3, 'months').hour(23).minute(59).second(59)
								.toDate().getTime()
							break
						case 'oneYear':
							time = moment().tz("Asia/Shanghai").add(1, 'years').hour(23).minute(59).second(59)
								.toDate().getTime()
							break
					}
					let data = {
						'vipInfo': {
							storeVipCardInfo: {
								cardId: vipCard._id,
								cardImageUrl: vipCard.imageUrl,
								cardName: vipCard.name,
								expirationTime: time,
								settlementWay: vipCard.settlementWay,
								time: vipCard.time,
								level: vipCard.level
							}
						}
					}
					if (vipCard.settlementWay == 'time' && vipCard.time == 'oneYear') {
						data.serviceRemainTimes = {}
					}
					await transaction.collection("uni-id-users").doc(user._id).update(data)
				}
			} else if (vipCard.type == 'merchant') {
				if (user.vipInfo) {
					let time
					if (user.vipInfo.merchantVipCardInfo && user.vipInfo.merchantVipCardInfo.expirationTime >
						Date.now()) {
						// 未过期
						time = moment(user.vipInfo.merchantVipCardInfo.expirationTime).tz("Asia/Shanghai").add(
							1, 'years').hour(23).minute(59).second(59).toDate().getTime()
					} else {
						time = moment().tz("Asia/Shanghai").add(1, 'years').hour(23).minute(59).second(59)
							.toDate().getTime()
					}
					await transaction.collection("uni-id-users").doc(user._id).update({
						'vipInfo.merchantVipCardInfo': {
							cardId: vipCard._id,
							cardImageUrl: vipCard.imageUrl,
							cardName: vipCard.name,
							expirationTime: time,
							settlementWay: vipCard.settlementWay,
							time: vipCard.time,
							level: vipCard.level
						},
						serviceRemainTimes: {}
					})
				} else {
					user.vipInfo = {}
					let copyUser = JSON.parse(JSON.stringify(user))
					delete copyUser._id
					await transaction.collection("uni-id-users").doc(user._id).set(copyUser)
					let time = moment().tz("Asia/Shanghai").add(1, 'years').hour(23).minute(59).second(59)
						.toDate().getTime()
					await transaction.collection("uni-id-users").doc(user._id).update({
						'vipInfo': {
							merchantVipCardInfo: {
								cardId: vipCard._id,
								cardImageUrl: vipCard.imageUrl,
								cardName: vipCard.name,
								expirationTime: time,
								settlementWay: vipCard.settlementWay,
								time: vipCard.time,
								level: vipCard.level
							}
						},
						serviceRemainTimes: {}
					})
				}
			}
		} catch (e) {
			throw e
		}
	},

	refundNow: async function({
		order,
		reason,
		serviceChargeRate = 0, //退款手续费比例，0表示无手续费，1表示全扣
		transaction
	}) {
		try {
			if (order.total_fee) {
				let refundFee
				if (order.couponId) {
					await transaction.collection('t3ds-coupon-member').doc(order.couponId).update({
						used: false,
						usedTime: '',
						updateTime: Date.now(),
						updateBy: '系统'
					});
					let totalFee = order.total_fee - order.discount_fee
					refundFee = totalFee - Math.round(totalFee * serviceChargeRate)
				} else {
					refundFee = order.total_fee - Math.round(order.total_fee * serviceChargeRate)
				}
				let account = await dbHelper.getOne("t3ds-account", {
					userId: order.user_id
				})
				// 需要发起微信退款的钱, 需要退回余额的钱
				let refundFee2, refundBalance;
				if (order.use_balance) {
					// 使用了多少余额里面的钱
					let balance = order.total_fee - order.payment_fee;

					if (refundFee > balance) {
						refundBalance = balance;
						refundFee2 = refundFee - balance;
					} else {
						refundBalance = refundFee;
					}
					console.log("退至余额的金额", (refundBalance / 100).toFixed(2));
					account.balance += refundBalance;
					account.total += refundBalance;
					await transaction.collection("t3ds-account").doc(account._id).update({
						balance: dbCmd.inc(refundBalance),
						total: dbCmd.inc(refundBalance)
					})
					let accountLog = {
						accountId: account._id,
						userId: order.user_id,
						createTime: Date.now(),
						income: refundBalance,
						orderId: order._id,
						total: account.total + refundBalance,
						tradeType: 6
					}
					await dbHelper.insert("t3ds-account-log", accountLog, transaction);
				} else {
					refundFee2 = refundFee;
				}
				let refundApply = {
					orderSn: order._id,
					createTime: Date.now(),
					reason,
					auditBy: '系统',
					auditTime: Date.now(),
					status: "REFUNDED",
					fullRefund: serviceChargeRate == 0,
					serviceChargeRate
				}
				if (refundBalance) {
					refundApply.refundBalance = refundBalance;
				}
				var orderStatus = 8; // 已退款
				if (refundFee2) {
					console.log("退至第三方账户的金额", (refundFee2 / 100).toFixed(2));
					refundApply.refundFee = refundFee2;
					refundApply.status = "REFUNDING";
					orderStatus = 7; //退款中
				} else {
					refundApply.refundTime = Date.now();
				}

				await dbHelper.insert("t3ds-refund-apply", refundApply, transaction);
				await transaction.collection("t3ds-order").doc(order._id).update({
					status: orderStatus,
					refundReason: reason,
					update_time: Date.now()
				})

				if (order.couponId) {
					await dbHelper.update("t3ds-coupon-member", {
						_id: order.couponId,
						used: false,
						usedTime: dbCmd.set('')
					}, transaction);
				}

				if (refundFee2) {
					console.log("发起微信退款", order);
					let uniPayInstance = payUtil.getPayInstance(order.pay_type, order.platform);
					let res = await uniPayInstance.refund({
						outTradeNo: order._id,
						outRefundNo: refundApply._id,
						totalFee: Math.round(order.payment_fee), // 订单总金额，支付宝可不填此项
						refundFee: Math.round(refundFee2), // 退款总金额
					})
				}
				order.status = orderStatus;
				order.update_time = Date.now();
			} else {
				let refundApply = {
					_id: applyId,
					auditBy: '系统',
					auditTime: Date.now(),
					refundFee: 0,
					status: "REFUNDED",
					refundTime: Date.now()
				}
				await dbHelper.update("t3ds-order", {
					_id: order._id,
					status: 8
				}, transaction)

				await dbHelper.update("t3ds-refund-apply", refundApply, transaction)
				order.status = 8;
				order.update_time = Date.now();
			}
		} catch (e) {
			console.log("立即退款遇到错误，事务回滚", e);
			throw e
		}
	}
}
